package com.yuchting.dinneronline.client;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.cell.client.AbstractEditableCell;
import com.google.gwt.cell.client.ButtonCell;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.EditTextCell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.view.client.DefaultSelectionEventManager;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionModel;
import com.google.gwt.view.client.SingleSelectionModel;
import com.yuchting.dinneronline.client.common.CommonDialog;
import com.yuchting.dinneronline.client.common.Dinner;
import com.yuchting.dinneronline.client.common.YesNoHandler;
import com.yuchting.dinneronline.client.common.YuchJSONObject;
import com.yuchting.dinneronline.share.ShareField;

public class DinnerPanel extends VerticalPanel {
	
	final MainPanel	m_mainPanel;
	
	// interface to get the value of host's attribute
	private static interface GetValue<C> {
		C getValue(Dinner contact);
	}
	
	final ProvidesKey<Dinner> m_privdesKey = new ProvidesKey<Dinner>() {
	     public Object getKey(Dinner item) {
	    	 return item == null ? null : item.getName();
	     }
   };

	final CellTable<Dinner> m_table		= new CellTable<Dinner>(m_privdesKey);	
	final List<AbstractEditableCell<?, ?>> m_editableCells = new ArrayList<AbstractEditableCell<?, ?>>();
	ListDataProvider<Dinner> m_dinnerList 	= new ListDataProvider<Dinner>();
	
	final AsyncCallback<String>	m_changeCallback	= new AsyncCallback<String>(){
		public void onFailure(Throwable caught) {
			CommonDialog.PopupPrompt("change 菜单 exception:" + caught.getMessage(),m_table);
		}

		public void onSuccess(String result) {}
	};
	
	final static String	fsm_dinnerNameWidth 	= "180px";
	final static String 	fsm_dinnerPriceWidth	= "100px";
	final static String	fsm_dinnerOpBtnWidth	= "100px";
	
	
	private static DinnerPanel sm_dinnerPanel; 
	public DinnerPanel(MainPanel _main){
		
		sm_dinnerPanel = this;
		
		m_mainPanel = _main;
		
	    ListHandler<Dinner> sortHandler = new ListHandler<Dinner>(m_dinnerList.getList());
	    m_table.addColumnSortHandler(sortHandler);
	    m_table.setPageSize(5000);
	    
	    // Add a selection model so we can select cells.
	    final SelectionModel<Dinner> selectionModel = new SingleSelectionModel<Dinner>(m_privdesKey);
	    m_table.setSelectionModel(selectionModel,DefaultSelectionEventManager.<Dinner> createDefaultManager());
	    
	    // dinner name
	    Column<Dinner,String> t_column = addColumn(new TextCell(),"菜名",new GetValue<String>(){
	    	public String getValue(Dinner dinner){
	    		return dinner.getName();
	    	}
	    },null);
	    m_table.setColumnWidth(t_column, fsm_dinnerNameWidth);
	    	    
	    // price 
	    t_column = addColumn(new EditTextCell(),"菜价",new GetValue<String>(){
	    	public String getValue(Dinner dinner){
	    		return Double.toString(dinner.getPrice());
	    	}
	    },new FieldUpdater<Dinner,String>(){
	    	public void update(int index, Dinner object, String value){
	    		
	    		try{
	    			object.setPrice(Double.valueOf(value).doubleValue());
	    		}catch(Exception e){
	    			CommonDialog.PopupPrompt("菜价 exception:" + e.getMessage(),m_table);
	    		}
	    		
	    		changeSvrDinner(object);
	    	}
	    });
	    m_table.setColumnWidth(t_column, fsm_dinnerPriceWidth);
	    
	    // add delete button column
	    //
	    t_column = addColumn(new ButtonCell(),"删除",new GetValue<String>(){
	    	public String getValue(Dinner object){
	    		return "X";
	    	}
	    	
	    },new FieldUpdater<Dinner, String>() {
	    	public void update(int index, final Dinner object, String value){
    		
	    		CommonDialog.PopupYesNoDlg("你真的要删除 [" + object.getName() + "] 这个菜么?",
				new YesNoHandler(){
					public void Process(){
						
						try{
							MainPage.fsm_server.delDinner(object.getName(),m_changeCallback);
						}catch(Exception e){
							CommonDialog.PopupPrompt("删除菜 exception:" + e.getMessage(),m_table);
						}
						
						m_dinnerList.getList().remove(object);	    		
			    		m_table.redraw();
					}
	    		},null);
	    		
	    	}
		});
	    m_table.setColumnWidth(t_column, fsm_dinnerOpBtnWidth);
	    
	    m_dinnerList.addDataDisplay(m_table);
	    add(m_table);
	    
	    // add the new dinner increase field
	    //
	    HorizontalPanel t_addPanel = new HorizontalPanel();
	    t_addPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
	    
	    final TextBox t_dinnerName		= new TextBox();
	    final TextBox t_dinnerPrice		= new TextBox();
	    final Button t_addBtn = new Button("添加菜单");
	    
	    t_dinnerName.setWidth(fsm_dinnerNameWidth);
	    t_dinnerPrice.setWidth(fsm_dinnerPriceWidth);
	    t_addBtn.setWidth(fsm_dinnerOpBtnWidth);
	    
	    t_addBtn.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				String t_name = t_dinnerName.getText();
				if(t_name.isEmpty()){
					CommonDialog.PopupPrompt("需要填写英文名来表示惟一的菜单",t_dinnerName);
					return;
				}
				
				for(Dinner d:m_dinnerList.getList()){
					if(d.getName().equals(t_name)){
	    				CommonDialog.PopupPrompt("已经有个菜单叫 " + t_name,t_dinnerName);
						return;
					}
				}
				
				if(!ShareField.isLeagalName(t_name)){
					CommonDialog.PopupPrompt("名字不能带有符号",t_dinnerName);
					return;
				}
								
				double t_price;
				try{
					t_price = Double.valueOf(t_dinnerPrice.getText()).doubleValue();
				}catch(Exception e){
					CommonDialog.PopupPrompt("菜价非法，请填写数字",t_dinnerPrice);
					return;
				}
				
				try{
					final Dinner t_dinner = new Dinner();
					t_dinner.setName(t_name);
					t_dinner.setPrice(t_price);
					
					
					MainPage.fsm_server.addDinner(t_dinner.toJSON().toString(),new AsyncCallback<String>() {

						public void onFailure(Throwable caught) {
							CommonDialog.PopupPrompt("exception:" + caught.getMessage(),m_table);
						}

						public void onSuccess(String result){
							if(result.startsWith("<OK />")){
								m_dinnerList.getList().add(t_dinner);
								m_dinnerList.refresh();
								
								t_dinnerName.setText("");
								t_dinnerPrice.setText("");
								
								return;
							}
							
							CommonDialog.PopupPrompt(result,m_table);
						}
						
					});
				}catch(Exception e){
					CommonDialog.PopupPrompt("change 中文菜名 exception:" + e.getMessage(),m_table);
				}
			}
		});
	    
	    t_addPanel.add(t_dinnerName);
	    t_addPanel.add(t_dinnerPrice);
	    t_addPanel.add(t_addBtn);
	    
	    add(t_addPanel);
	}
	
	private <C> Column<Dinner, C> addColumn(Cell<C> cell, String headerText,
			final GetValue<C> getter, FieldUpdater<Dinner, C> fieldUpdater) {
		
		Column<Dinner, C> column = new Column<Dinner, C>(cell) {
			@Override
			public C getValue(Dinner object) {
				if(getter != null){
					return getter.getValue(object);
				}else{
					return null;
				}				
			}
		};
		
		column.setFieldUpdater(fieldUpdater);
		
		if (cell instanceof AbstractEditableCell<?, ?>) {
			m_editableCells.add((AbstractEditableCell<?, ?>) cell);
		}
		
		m_table.addColumn(column, headerText);
		
	    return column;
	}
	
	private void changeSvrDinner(Dinner _dinner){
		try{
			MainPage.fsm_server.modifyDinner(_dinner.getName(),_dinner.toJSON().toString(),m_changeCallback);
		}catch(Exception e){
			CommonDialog.PopupPrompt("change 中文菜名 exception:" + e.getMessage(),m_table);
		}
	}
	
	// will be called by OrderPanel.processCurrDinnerList when request dinner list successfully
	public static 	void refreshDinnerList(JSONArray _array){
		if(sm_dinnerPanel != null){
			sm_dinnerPanel.refreshDinnerListImpl(_array);
		}
	}
	
	private void refreshDinnerListImpl(JSONArray _array){
		m_dinnerList.getList().clear();
				
		int num = _array.size();
		for(int i = 0 ;i < num;i++){
			final Dinner t_dinner = new Dinner();
			t_dinner.fromJSON(new YuchJSONObject((JSONObject)_array.get(i)));
			
			m_dinnerList.getList().add(t_dinner);
		}
		
		m_dinnerList.refresh();
	}
}
